package xconcurrent

import (
	"context"
	"fmt"
	"gitee.com/xfrm/middleware/xlog"
	"time"
)

type Locker interface {
	LockWithTimeout(ctx context.Context, key string, value interface{}, expiration, timeout time.Duration) (r bool, err error)
	Unlock(ctx context.Context, key string, value interface{}) (bool, error)
}

//分布式锁代码段
//降级了的分布式锁。如果缓存挂掉了，则放弃分布式锁失效
func DistributeLockExec(ctx context.Context, locker Locker, lockKey string, expiration, timeout time.Duration, exec func() error, execWhenError bool) (bool, error) {
	fun := "DistributeLockExec -->"
	lockVal := fmt.Sprintf("%d", time.Now().Nanosecond())
	defer func() {
		r, err := locker.Unlock(ctx, lockKey, lockVal)
		if err != nil {
			xlog.Errorf(ctx, "%s  unlock error: lockKey: %s, lockVal: %s, err: %v ", fun, lockKey, lockVal, err)
		}
		if !r {
			xlog.Errorf(ctx, "%s  unlock fail: lockKey: %s, lockVal: %s ", fun, lockKey, lockVal)
		}
	}()
	r, err := locker.LockWithTimeout(ctx, lockKey, lockVal, expiration, timeout)
	if err != nil {
		xlog.Errorf(ctx, "%s lock error: lockKey: %s, lockVal: %s, err: %v ", fun, lockKey, lockVal, err)
		if execWhenError {
			return false, exec()
		}
		return false, err
	}
	if r {
		return r, exec()
	}
	xlog.Warnf(ctx, "%s lock fail: lockKey: %s, lockVal: %s ", fun, lockKey, lockVal)
	return r, nil
}
